package abi

import (
	"context"
	"errors"
	"fmt"
	"github.com/ethereum/go-ethereum/accounts/abi/bind"
	"github.com/ethereum/go-ethereum/common"
	"math/big"
	"os"
	"strings"
	"time"
)

// GetOwner 获取Owner地址
func GetOwner() (owner common.Address, err error) {
	owner, err = LotteryObj.Owner(nil)
	if err != nil {
		return
	}
	return
}

// GetPeriods 获取彩票期数
func GetPeriods() (periods uint8, err error) {
	periods, err = LotteryObj.Periods(nil)
	if err != nil {
		return
	}
	return
}

func getOps(username, pwd string, isTransaction bool) (*bind.TransactOpts, error) {
	newUsername := username[2:]
	newUsername = strings.ToLower(newUsername)
	var keyPath string
	keyStoreDir := "/home/legend/WorkSpace/block_chain/legend/keystore/"
	files, err := os.ReadDir(keyStoreDir)
	if err != nil {
		return nil, err
	}
	for _, file := range files {
		if strings.Contains(file.Name(), newUsername) {
			keyPath = keyStoreDir + file.Name()
		}
	}
	if keyPath == "" {
		return nil, errors.New("用户名不存在")
	}
	file, err := os.ReadFile(keyPath)
	if err != nil {
		return nil, err
	}
	chainID, err := client.ChainID(context.Background())
	if err != nil {
		panic("获取chainID失败")
	}
	ops, err := bind.NewTransactorWithChainID(strings.NewReader(string(file)),
		pwd, chainID)
	if err != nil {
		fmt.Println(err.Error())
		panic("初始化交易信息失败")
	}
	if isTransaction {
		ops.GasLimit = uint64(3000000)
		ops.GasPrice = big.NewInt(20000)
		// 此次交易的值
		ops.Value = big.NewInt(1000000000000000000)
	}

	ops.From = common.HexToAddress(username)
	return ops, nil
}

func Bet(username, pwd string, nums []*big.Int) error {
	ops, err := getOps(username, pwd, true)
	if err != nil {
		return err
	}
	//函数中不修改状态变量，则不发生交易，传nil传输即可
	//如果函数中改变了状态变量，就需要发生交易，而这个函数就要用payable修饰，因为调用这个函数的时候必须要发起交通，待这个交易确认后，调用的这个函数产生的结果才会生效
	_, err = LotteryObj.Betting(ops, common.HexToAddress(username), nums)
	if err != nil {
		return err
	}
	return nil
}

type Account struct {
	Addr common.Address
	Nums []int64
}

//func GetBetInfos() (string, string, error) {
//	addrMaps := []map[string]string{}
//	var addrS Account
//	var i int64 = 0
//	for {
//		addrStruct, err := LotteryObj.Accounts(nil, big.NewInt(i))
//		if err != nil {
//			break
//		}
//
//		err = addrStruct.Scan(&addrS)
//		if err != nil {
//			break
//		}
//		addrMap := map[string]string{}
//		addrMap[addrS.Addr] = addrS.Nums
//	}
//}

func LotteryDraw() ([]*big.Int, error) {
	// 先获取期数，开奖后期数会增加1
	periods, err := GetPeriods()
	if err != nil {
		return []*big.Int{}, err
	}
	ops, err := getOps("", "", false)
	if err != nil {
		return []*big.Int{}, nil
	}
	_, err = LotteryObj.LotteryDrawing(ops)
	// 开奖成功后立马获取开奖结果报错，错误信息为 attempting to unmarshall an empty string while arguments are expected
	if err != nil {
		return []*big.Int{}, err
	}
	// 太快，睡5秒
	time.Sleep(5 * time.Second)
	// todo 待测试死循环取值
	for {
		_, err := LotteryObj.LotteryResultsHistory(nil, periods, big.NewInt(0))
		if err == nil {
			break
		}
		time.Sleep(1 * time.Second)
	}
	nums := make([]*big.Int, 0)
	for i := 0; i < 6; i++ {
		num, err := LotteryObj.LotteryResultsHistory(nil, periods, big.NewInt(int64(i)))
		if err != nil {
			return []*big.Int{}, err
		}
		nums = append(nums, num)
	}
	return nums, nil
}
